home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / programr / upc12bs2.zip / UTIL / gensig.c < prev    next >
C/C++ Source or Header  |  1993-09-27  |  22KB  |  575 lines

  1. /*--------------------------------------------------------------------*/
  2. /*       Program:    gensig.c             24 July 1991                */
  3. /*       Author:     Andrew H. Derbyshire                             */
  4. /*       Address:    ahd@kew.com                                      */
  5. /*       Function:   Append a random quote to an electronic           */
  6. /*                   mail signature file                              */
  7. /*       Language:   Borland C++ 2.0 (in ANSI C mode)                 */
  8. /*       Arguments:  Name of file with fixed text input               */
  9. /*                   Name of file with variable quotes                */
  10. /*                   Name of file to be written                       */
  11. /*--------------------------------------------------------------------*/
  12.  
  13. /*--------------------------------------------------------------------*/
  14. /*                          RCS Information                           */
  15. /*--------------------------------------------------------------------*/
  16.  
  17. /*
  18.  *    $Id: gensig.c 1.4 1993/09/27 04:04:06 ahd Exp $
  19.  *
  20.  *    Revision history:
  21.  *    $Log: gensig.c $
  22.  * Revision 1.4  1993/09/27  04:04:06  ahd
  23.  * Suppress compiler warning message
  24.  *
  25.  * Revision 1.3  1993/04/11  00:33:54  ahd
  26.  * Global edits for year, TEXT, etc.
  27.  *
  28.  * Revision 1.2  1993/03/06  23:04:54  ahd
  29.  * Alter message to include output files
  30.  *
  31.  * Revision 1.1  1992/11/15  04:29:22  ahd
  32.  * Initial revision
  33.  *
  34.  */
  35.  
  36. static char rcsid[] = "$Id: gensig.c 1.4 1993/09/27 04:04:06 ahd Exp $";
  37.  
  38. /*--------------------------------------------------------------------*/
  39. /*                       Standard include files                       */
  40. /*--------------------------------------------------------------------*/
  41.  
  42. #include <stdio.h>
  43. #include <stdlib.h>
  44. #include <io.h>
  45. #include <direct.h>
  46. #include <sys/types.h>
  47. #include <sys/stat.h>
  48. #include <string.h>
  49. #include <time.h>
  50.  
  51. /*--------------------------------------------------------------------*/
  52. /*                    UUPC/extended include files                     */
  53. /*--------------------------------------------------------------------*/
  54.  
  55. #include "lib.h"
  56. #include "timestmp.h"
  57.  
  58. /*--------------------------------------------------------------------*/
  59. /*                            Local macros                            */
  60. /*--------------------------------------------------------------------*/
  61.  
  62. #define bitsper(s) (8 * (sizeof s))
  63.  
  64. #define bitflag(x, s) (1 << ((bitsper(s) - 1) - x))
  65.  
  66. #define biton( s, offset ) \
  67.                (( s[ (size_t) (offset / bitsper(*s)) ] ) & \
  68.                 bitflag(offset % bitsper( *s ), *s))
  69.  
  70. #define bitoff( s, offset) (!biton(s, offset))
  71.  
  72. /*--------------------------------------------------------------------*/
  73. /*                    Internal function prototypes                    */
  74. /*--------------------------------------------------------------------*/
  75.  
  76. static void usage( void );
  77.  
  78. static long chooseit( struct stat *current_status,
  79.        const char *lookaside,
  80.                  const char *quoteused,
  81.                  const char *fname ,
  82.                  const char *target);
  83.  
  84. static long getquote( const char *data, const char *target);
  85.  
  86. static void CopyQuote( const char *fname, long where, FILE *stream);
  87.  
  88. static void CopyFixed( const char *fname, FILE *stream );
  89.  
  90. static long chooseavailable( const char *quoteused, long quotes );
  91.  
  92. currentfile();
  93.  
  94. /*--------------------------------------------------------------------*/
  95. /*    m a i n                                                         */
  96. /*                                                                    */
  97. /*    main program                                                    */
  98. /*--------------------------------------------------------------------*/
  99.  
  100. void main( int argc, char **argv)
  101. {
  102.  
  103.    long where;
  104.    FILE *stream;
  105.  
  106.    banner( argv );
  107.  
  108. /*--------------------------------------------------------------------*/
  109. /*                  Validate the number of arguments                  */
  110. /*--------------------------------------------------------------------*/
  111.  
  112.       if ( argc !=  4 )
  113.          usage();
  114.  
  115. /*--------------------------------------------------------------------*/
  116. /*    Determine the number of the quotes available, and then          */
  117. /*    select one                                                      */
  118. /*--------------------------------------------------------------------*/
  119.  
  120.       where = getquote( argv[2], argv[3] );
  121.  
  122. /*--------------------------------------------------------------------*/
  123. /*                      Open up our output file                       */
  124. /*--------------------------------------------------------------------*/
  125.  
  126.       stream = fopen( argv[3] , "w");
  127.       if ( stream == NULL )
  128.       {
  129.          perror( argv[3] );
  130.          exit(1);
  131.       }
  132.  
  133. /*--------------------------------------------------------------------*/
  134. /*           Copy the fixed and variable parts of the file            */
  135. /*--------------------------------------------------------------------*/
  136.  
  137.       CopyFixed( argv[1], stream );
  138.       CopyQuote( argv[2], where, stream );
  139.  
  140. /*--------------------------------------------------------------------*/
  141. /*                   Close up and return to caller                    */
  142. /*--------------------------------------------------------------------*/
  143.  
  144.       fclose( stream );
  145.       exit( 0 );
  146.  
  147. } /* main */
  148.  
  149. /*--------------------------------------------------------------------*/
  150. /*    u s a g e                                                       */
  151. /*                                                                    */
  152. /*    Report program usage and then exit                              */
  153. /*--------------------------------------------------------------------*/
  154.  
  155. static void usage( void )
  156. {
  157.    printf("Usage:\tgensig\taddr-file quote-file output-file\n");
  158.    printf("\taddr-file\tFixed portion of signature file\n");
  159.    printf("\tquote-file\tFile of quotes, separated by delimiter lines\n");
  160.    printf("\toutput-file\tOutput file with fixed portion and single quote\n");
  161.    exit( 2 );
  162. } /* usage */
  163.  
  164. /*--------------------------------------------------------------------*/
  165. /*    g e t q u o t e                                                 */
  166. /*                                                                    */
  167. /*    Select a quote to process                                       */
  168. /*--------------------------------------------------------------------*/
  169.  
  170. static long getquote( const char *data, const char *target)
  171. {
  172.    struct stat current_status;
  173.    long where;
  174.  
  175.    char lookaside[FILENAME_MAX];
  176.    char quoteused[FILENAME_MAX];
  177.    char drive[FILENAME_MAX],
  178.         dir[FILENAME_MAX],
  179.         file[FILENAME_MAX],
  180.         ext[FILENAME_MAX];
  181.  
  182. /*--------------------------------------------------------------------*/
  183. /*       Get size and data information on the quotes data file        */
  184. /*--------------------------------------------------------------------*/
  185.  
  186.    if(stat((char *) data, ¤t_status ) <0)
  187.    {
  188.       perror( data );         /* If no data file, panic gracefully   */
  189.       exit( 3 );
  190.    } /* if */
  191.  
  192. /*--------------------------------------------------------------------*/
  193. /*       Build the lookaside file name from the data file name        */
  194. /*--------------------------------------------------------------------*/
  195.  
  196. #ifdef __TURBOC__
  197.    fnsplit( data, drive, dir, file, ext);
  198.    fnmerge( lookaside, drive, dir, file, ".las");
  199.    fnmerge( quoteused, drive, dir, file, ".qus");
  200. #else
  201.    _splitpath( data, drive, dir, file, ext);
  202.    _makepath( lookaside, drive, dir, file, ".las");
  203.    _makepath( quoteused, drive, dir, file, ".qus");
  204. #endif /* __TURBOC__ */
  205.  
  206. /*--------------------------------------------------------------------*/
  207. /*    Now get the location of the quote; if it fails the first        */
  208. /*    time, then the lookaside buffer is updated and we can try       */
  209. /*    again                                                           */
  210. /*--------------------------------------------------------------------*/
  211.  
  212.    where = chooseit( ¤t_status, lookaside, quoteused, data , target);
  213.    if  (where == -1 )
  214.    {
  215.       where = chooseit( ¤t_status, lookaside, quoteused, data, target );
  216.       if ( where == - 1)
  217.       {
  218.          printf("Unable to create lookaside file \"%s\"!\n",
  219.                   lookaside );
  220.          exit( 4 );
  221.       } /* if ( where == - 1) */
  222.    } /* if ( where == - 1) */
  223.  
  224. /*--------------------------------------------------------------------*/
  225. /*                          Return to caller                          */
  226. /*--------------------------------------------------------------------*/
  227.  
  228.    return where;
  229.  
  230. } /* getquote */
  231.  
  232. /*--------------------------------------------------------------------*/
  233. /*    c h o o s e i t                                                 */
  234. /*                                                                    */
  235. /*    Returns number of quotes in file                                */
  236. /*--------------------------------------------------------------------*/
  237.  
  238. static long chooseit( struct stat *current_status,
  239.                  const char *lookaside,
  240.                  const char *quoteused,
  241.                  const char *fname,
  242.                  const char *target)
  243. {
  244.    FILE *stream;
  245.    FILE *data;
  246.    long where;
  247.    long quotes = 0;
  248.    long quote;
  249.  
  250.    char buf[BUFSIZ];
  251.    char delimiter[BUFSIZ];
  252.  
  253. /*--------------------------------------------------------------------*/
  254. /*    Open up the lookaside file and determine if it is up to         */
  255. /*    date.  If so, choose an entry and return it.                    */
  256. /*--------------------------------------------------------------------*/
  257.  
  258.    stream = fopen( lookaside , "rb" );
  259.    if ( stream != NULL )
  260.    {
  261.       struct stat status;
  262.       fread( &status, sizeof status, 1, stream);
  263.       if ((status.st_size == current_status->st_size) &&
  264.           (status.st_mtime == current_status->st_mtime))
  265.       {                       /* Lookaside file up to date, use it   */
  266.          if( stat((char *) lookaside, &status ) < 0)
  267.          {
  268.             perror( lookaside );
  269.             exit( 5 );
  270.          } /* if */
  271.  
  272.          quotes = (status.st_size - sizeof status) / sizeof where;
  273.                               /* Determine number of quote pointers
  274.                                  in lookaside file from the file's
  275.                                  length                              */
  276.  
  277.          quote = chooseavailable( quoteused, quotes);
  278.  
  279.          fseek( stream, quote * sizeof where , SEEK_CUR );
  280.                               /* Step required number of quotes
  281.                                  into the file                       */
  282.          fread( &where, sizeof where, 1, stream);
  283.                               /* Read offset in data file of quote   */
  284.          printf("Chose quote %ld of %ld from %s for %s:\n\n",
  285.                   quote + 1 , quotes, fname, target);
  286.                               /* Announce number of quote of the day */
  287.          fclose( stream );    /* Done with lookaside file, of course */
  288.          return where;        /* Return position in file to caller   */
  289.       } /* if */
  290.       else
  291.          fclose( stream );
  292.    } /* if ( stream != NULL ) */
  293.    else
  294.       perror( lookaside );
  295.  
  296. /*--------------------------------------------------------------------*/
  297. /*               We have to rewrite the lookaside file                */
  298. /*--------------------------------------------------------------------*/
  299.  
  300.    unlink( quoteused );          /* Make all quotes available        */
  301.  
  302.    data   = fopen( fname, "rt");          /* Open data file to scan  */
  303.    if ( data == NULL )                    /* Did it open?            */
  304.    {
  305.       perror( fname );                    /* No --> Error            */
  306.       exit( 6 );
  307.    }
  308.  
  309.    stream = fopen( lookaside , "wb" );    /* Open lookaside file     */
  310.    if ( stream == NULL )                  /* Did it open?            */
  311.    {
  312.       perror( lookaside );                /* No --> Error            */
  313.       exit( 7 );
  314.    }
  315.  
  316. /*--------------------------------------------------------------------*/
  317. /*    Start the new lookaside file with the status of the data        */
  318. /*    file for later comparisons                                      */
  319. /*--------------------------------------------------------------------*/
  320.  
  321.    fwrite( current_status, sizeof *current_status, 1, stream);
  322.  
  323. /*--------------------------------------------------------------------*/
  324. /*    Get the first line of the file, which will contain the          */
  325. /*    delimiter line                                                  */
  326. /*--------------------------------------------------------------------*/
  327.  
  328.    fgets(delimiter, BUFSIZ, data );
  329.    where = ftell( data );  /* Get location of possible first quote   */
  330.  
  331. /*--------------------------------------------------------------------*/
  332. /*                  Now process the rest of the file                  */
  333. /*--------------------------------------------------------------------*/
  334.  
  335.    while( fgets(buf, BUFSIZ, data ) != NULL )
  336.    {
  337.       if ( strcmp( buf, delimiter ))   /* Delimiter line?            */
  338.       {                                /* No --> data line           */
  339.          if ( where != -1L )  /* First line of new quote?            */
  340.          {                    /* Yes --> Write location to lookaside */
  341.             quotes ++ ;
  342.             fwrite( &where, sizeof where, 1, stream);
  343.             where = -1L;
  344.          } /* if */
  345.       } /* if */
  346.       else
  347.          where = ftell( data );        /* Delimiter line, remember
  348.                                           location of NEXT line in
  349.                                           file                       */
  350.    } /* while */
  351.  
  352. /*--------------------------------------------------------------------*/
  353. /*                 Close up shop and return to caller                 */
  354. /*--------------------------------------------------------------------*/
  355.  
  356.    fclose( stream );
  357.    fclose( data );
  358.  
  359.    if ( quotes == 1 )
  360.    {
  361.       printf("Invalid data file; first line not a delimiter line!");
  362.       exit( 99 );
  363.    }
  364.  
  365.    printf("Updated lookaside file %s with %d quotes.\n",
  366.                lookaside , quotes);
  367.  
  368.    return -1;                 /* Inform caller that lookaside
  369.                                  file was updated                    */
  370. } /* chooseit */
  371.  
  372. /*--------------------------------------------------------------------*/
  373. /*    c h o o s e a v a i l a b l e                                   */
  374. /*                                                                    */
  375. /*    Select a quote from available list                              */
  376. /*--------------------------------------------------------------------*/
  377.  
  378. static long chooseavailable( const char *quoteused, long quotes )
  379. {
  380.    FILE *stream;
  381.    unsigned char *quotelist;
  382.  
  383.    size_t listsize = (size_t) (( quotes + bitsper(*quotelist) - 1 ) /
  384.                               bitsper(*quotelist));
  385.    long quote;
  386.    long available = quotes;
  387.    long select;
  388.  
  389. /*--------------------------------------------------------------------*/
  390. /*                 Initialize the bit array of quotes                 */
  391. /*--------------------------------------------------------------------*/
  392.  
  393.    quotelist = malloc( listsize );
  394.    checkref( quotelist );
  395.  
  396. /*--------------------------------------------------------------------*/
  397. /*             Open up the used quoted file, if possible              */
  398. /*--------------------------------------------------------------------*/
  399.  
  400.    stream = fopen( quoteused, "rb");
  401.  
  402. /*--------------------------------------------------------------------*/
  403. /*              Determine the number of available quotes              */
  404. /*--------------------------------------------------------------------*/
  405.  
  406.    if ( stream != NULL )
  407.    {
  408.  
  409.       if (fread (&available, sizeof available, 1 , stream) < 1 )
  410.       {
  411.          perror(  quoteused );
  412.          available = 0;
  413.       }
  414.       else if ( quotes <= available )
  415.          available = 0;
  416.       else if (fread (quotelist, sizeof *quotelist, listsize , stream) <
  417.                   listsize)
  418.       {
  419.          available = 0;
  420.          perror( quoteused );
  421.       }
  422.  
  423.       fclose( stream );
  424.    } /* if */
  425.    else
  426.       available = 0;
  427.  
  428.    if ( available <= ( quotes / 10 ))
  429.    {
  430.       memset( quotelist, '\0', listsize );
  431.       printf("Resetting available quotes list\n");
  432.       available = quotes;
  433.    }
  434.  
  435. /*--------------------------------------------------------------------*/
  436. /*                       Now, choose the quote                        */
  437. /*--------------------------------------------------------------------*/
  438.  
  439.    srand ( (unsigned) time( NULL )); /* Initialize the generator     */
  440.    select = rand() % available ; /* ... Lucky seven?                 */
  441.  
  442. /*--------------------------------------------------------------------*/
  443. /*                         end debugging info                         */
  444. /*--------------------------------------------------------------------*/
  445.  
  446.    quote = 0;
  447.    while( quote < quotes )
  448.    {
  449.       if ( bitoff( quotelist, quote ))
  450.          select--;
  451.  
  452.       if ( select > 0 )
  453.          quote++;
  454.       else
  455.          break;
  456.    }
  457.  
  458.    if ( quote == quotes )           /* Did we overflow the array?    */
  459.       panic();                      /* Must have a bug!              */
  460.  
  461. /*--------------------------------------------------------------------*/
  462. /*                Now update our data and write it out                */
  463. /*--------------------------------------------------------------------*/
  464.  
  465.    stream = fopen( quoteused, "wb");
  466.    if ( stream == NULL )
  467.    {
  468.       perror( quoteused );
  469.       panic();
  470.    }
  471.  
  472.    quotelist[ (size_t) (quote / bitsper(*quotelist)) ] |=
  473.                bitflag( quote % bitsper(*quotelist), *quotelist );
  474.  
  475.    available -= 1;
  476.  
  477.    fwrite(&available, sizeof available, 1 , stream);
  478.    fwrite(quotelist,  sizeof *quotelist, listsize , stream);
  479.    fclose( stream );
  480.  
  481. /*--------------------------------------------------------------------*/
  482. /*                   Return the quote to the caller                   */
  483. /*--------------------------------------------------------------------*/
  484.  
  485.    return quote;
  486.  
  487. } /* chooseavailable */
  488.  
  489. /*--------------------------------------------------------------------*/
  490. /*    C o p y F i x e d                                               */
  491. /*                                                                    */
  492. /*    Copy fixed input text (user name and address) to output file    */
  493. /*--------------------------------------------------------------------*/
  494.  
  495. static void CopyFixed( const char *fname, FILE *stream )
  496. {
  497.    FILE *input;
  498.    char buf[BUFSIZ];
  499.  
  500. /*--------------------------------------------------------------------*/
  501. /*                    Open input file for copying                     */
  502. /*--------------------------------------------------------------------*/
  503.  
  504.    input = fopen( fname, "r");
  505.    if ( input == NULL )
  506.    {
  507.       perror( fname );
  508.       exit ( 8 );
  509.    }
  510.  
  511. /*--------------------------------------------------------------------*/
  512. /*             Copy the fixed input to the signature file             */
  513. /*--------------------------------------------------------------------*/
  514.  
  515.    while( fgets( buf, BUFSIZ, input ) != NULL)
  516.       fputs( buf, stream );
  517.  
  518. /*--------------------------------------------------------------------*/
  519. /*                 Close up shop and return to caller                 */
  520. /*--------------------------------------------------------------------*/
  521.  
  522.    fclose( input );
  523.  
  524. } /* CopyFixed */
  525.  
  526. /*--------------------------------------------------------------------*/
  527. /*    C o p y Q u o t e                                               */
  528. /*                                                                    */
  529. /*    Write a quote to the output file                                */
  530. /*--------------------------------------------------------------------*/
  531.  
  532. static void CopyQuote( const char *fname, long where, FILE *stream)
  533. {
  534.    FILE *input;
  535.    char buf[BUFSIZ];
  536.    char delimiter[BUFSIZ];
  537.  
  538. /*--------------------------------------------------------------------*/
  539. /*         Open up the quotes file and get the delimiter line         */
  540. /*--------------------------------------------------------------------*/
  541.  
  542.    input = fopen( fname, "r");
  543.    if ( input == NULL )
  544.    {
  545.       perror( fname );
  546.       exit ( 9 );
  547.    }
  548.  
  549.    fgets(delimiter, BUFSIZ, input );
  550.  
  551. /*--------------------------------------------------------------------*/
  552. /*   Position to the beginning of the actual quote to be processed    */
  553. /*--------------------------------------------------------------------*/
  554.  
  555.    fseek( input, where , SEEK_SET );
  556.  
  557. /*--------------------------------------------------------------------*/
  558. /*      Copy the quote to both the signature file and the screen      */
  559. /*--------------------------------------------------------------------*/
  560.  
  561.    while( fgets( buf, BUFSIZ, input ) != NULL)
  562.    {
  563.       if (!strcmp( delimiter, buf ))   /* Delimiter line?            */
  564.          break;                        /* Yes --> End of quote       */
  565.       fputs( buf, stream );   /* Copy quote to signature file        */
  566.       fputs( buf, stdout );   /* Copy quote to screen                */
  567.    } /* while( fgets( buf, BUFSIZ, input ) != NULL) */
  568.  
  569. /*--------------------------------------------------------------------*/
  570. /*                 Close up shop and return to caller                 */
  571. /*--------------------------------------------------------------------*/
  572.  
  573.    fclose( input );
  574. } /* CopyQuote */
  575.